<?php
/**
 * Created by PhpStorm.
 * User: Jan-Home
 * Date: 2018/4/5 0005
 * Time: 18:13
 */

namespace Gitee\GiteeAPI;

use Gitee\Helper\CurlRequest;
use Ke\Uri;

abstract class CoreAPI
{
	
	const QUERY_ROLE = 'role';
	const ROLE_ALL = 'all';
	const ROLE_ADMIN = 'admin';
	const ROLE_MEMBER = 'member';
	
	const QUERY_ACCESSIBLE = 'accessible';
	const ACC_ALL = 'all';
	const ACC_PUBLIC = 'public';
	const ACC_PRIVATE = 'private';
	
	protected $uri;
	
	protected $baseUrl = 'https://gitee.com/api/';
	
	protected $version = 'v5';
	
	protected $appApi;
	
	/** @var CurlRequest */
	protected $lastRequest;
	
	/** @var string */
	protected $lastResponse;
	
	/** @var string */
	protected $lastError;
	
	protected $isUsePage = false;
	
	protected $perPageCount = 20;
	
	protected $queryOptions = [];
	
	protected $filterOptions = [
		// 每一项中，0位默认值
		self::QUERY_ROLE       => [
			0                => self::ROLE_ALL,
			1                => self::ROLE_ADMIN,
			2                => self::ROLE_MEMBER,
			self::ROLE_ALL   => self::ROLE_ALL,
			self::ROLE_ADMIN => self::ROLE_ADMIN,
			self::ROLE_ADMIN => self::ROLE_MEMBER,
		],
		self::QUERY_ACCESSIBLE => [
			0                 => self::ACC_ALL,
			1                 => self::ACC_PUBLIC,
			2                 => self::ACC_PRIVATE,
			self::ACC_ALL     => self::ACC_ALL,
			self::ACC_PUBLIC  => self::ACC_PUBLIC,
			self::ACC_PRIVATE => self::ACC_PRIVATE,
		],
	];
	
	public function __construct(AppAPI $appApi)
	{
		$this->appApi = $appApi;
		$this->onConstruct();
	}
	
	protected function onConstruct()
	{
	}
	
	public function uri($path = '', $query = null)
	{
		if (!isset($this->uri)) {
			$this->uri = new Uri("{$this->baseUrl}/{$this->version}/");
		}
		return $this->uri->newUri($path, $query);
	}
	
	public function app()
	{
		return $this->appApi->app();
	}
	
	public function getToken($isString = false)
	{
		$token = $this->app()->getSessionToken();
		if ($isString) {
			return $token->access_token;
		}
		return $token;
	}
	
	public function getTokenStr()
	{
		return $this->getToken(true);
	}
	
	public function request($path, $query = null)
	{
		$uri = $this->uri($path, $query);
		$this->prepareUri($uri);
		
		$this->lastRequest = CurlRequest::new($uri);
		$this->lastRequest->get();
		$this->lastResponse = trim($this->lastRequest->getResponse());
		
		if (empty($this->lastResponse))
			return false;
		$json = json_decode($this->lastResponse, true);
		if ($json === null || $json === false)
			return false;
		if (!empty($json['message'])) {
			$this->lastError = $json['message'];
			return false;
		}
		return $json;
	}
	
	public function getLastRequest()
	{
		return $this->lastRequest;
	}
	
	public function getLastError()
	{
		return $this->lastError;
	}
	
	public function getLastResponse()
	{
		return $this->lastResponse;
	}
	
	public function setUsePage(bool $isUse)
	{
		$this->isUsePage = $isUse;
		return $this;
	}
	
	public function resetUsePage(& $value)
	{
		$value = $this->isUsePage;
		$this->isUsePage = false;
		return $this;
	}
	
	public function setQueryOptions(array $options)
	{
		if (empty($this->queryOptions))
			$this->queryOptions = $options;
		else
			$this->queryOptions += $options;
		return $this;
	}
	
	public function setQueryOption(string $field, string $type)
	{
		$this->queryOptions[$field] = $type;
		return $this;
	}
	
	public function resetQueryOptions(& $value)
	{
		$value = $this->queryOptions;
		$this->queryOptions = [];
		return $this;
	}
	
	public function getFilterOptions(string $type)
	{
		$options = $this->filterOptions[$type] ?? [];
		if (!isset($options[0]))
			$options[0] = '';
		return $options;
	}
	
	public function filter(string $type, $value = null)
	{
		$options = $this->getFilterOptions($type);
		if (empty($options))
			return $value;
		if (is_numeric($value)) {
			$value = intval($value);
			if ($value === false)
				$value = 0;
		} else if (is_string($value)) {
			$value = trim($value);
		} else {
			$value = 0;
		}
		return $options[$value] ?? $options[0];
	}
	
	protected function prepareUri(Uri $uri)
	{
		$this->resetUsePage($isUsePage)->resetQueryOptions($queryOptions);
		$uri->setCleanEndSlash(true);
		$query = $uri->getQueryData();
		if (!is_array($query)) $query = [];
		$query['access_token'] = $this->getTokenStr();
		if ($isUsePage) {
			$query['per_page'] = $this->perPageCount;
			if (!isset($query['page']) || !is_numeric($query['page']) || $query['page'] <= 0)
				$query['page'] = 1;
		}
		if (!empty($queryOptions)) {
			foreach ($queryOptions as $field => $type) {
				$query[$field] = $this->filter($type, $query[$field] ?? null);
			}
		}
		$uri->mergeQuery($query);
		return $this;
	}
}